#!/bin/bash
# usage: 
# ========================  /配置在jenkins脚本里面的区块\  =========================
# 在构建脚本里面不需要注释
# 前置条件，项目需要被设置成公开项目（这个又需要其最近的父群组被设置成公开项目）
# 查看和编辑本项目的文件 这个也需要设置为公开
url_jenkins_scripts="https://gitee.com/xbazhen-docker/jenkins-springcloud/raw/master"

# # 以下需要取消注释然后复制到jenkins脚本里面
# file_build="build.sh"
# # 下载脚本
# cd $WORKSPACE
# curl -s -o ./$file_build $url_jenkins_scripts/devb/java/$file_build
# # 下面的 $WORKSPACE 是jenkins的内置变量
# sed -i "/^WORKSPACE=/ c\WORKSPACE=$WORKSPACE" $file_build
# # 执行脚本
# bash $file_build
# ========================  \配置在jenkins脚本里面的区块/  =========================



# ==========================  /先决条件检查\  =================================
# 1. 检查docker，这个要用来构建镜像，以及pull和push镜像，暂略~
# 2. 检查harbor仓库，暂略~
# 3. 检查kubectl客户端是否工作正常，暂略~
# ==========================  \先决条件检查/  =================================

# ==========================  <引入jenkins变量>  =================================
WORKSPACE=
# ==========================  <下载文件>  =================================
# 进入工作目录
cd $WORKSPACE
[ ! -d "./jenkins_build" ]               && mkdir -p "./jenkins_build"
[ ! -d "./jenkins_build/docker" ]        && mkdir -p "./jenkins_build/docker"
[ ! -d "./jenkins_build/kubernetes" ]    && mkdir -p "./jenkins_build/kubernetes"
# 下载构建需要的配置文件,其中有两个空文件，不需要下载，会自动生成。
# docker需要下载的文件
# curl -s -o ./jenkins_build/docker/Dockerfile        $url_jenkins_scripts/devb/docker/Dockerfile_java
curl -s -o ./jenkins_build/docker/Dockerfile_java   $url_jenkins_scripts/devb/docker/Dockerfile_java
curl -s -o ./jenkins_build/docker/Dockerfile_nginx  $url_jenkins_scripts/devb/docker/Dockerfile_nginx
curl -s -o ./jenkins_build/docker/Dockerfile_python $url_jenkins_scripts/devb/docker/Dockerfile_python
# kubernetes需要下载的文件
kubernetes_list=(
    deployment_1.yml
    deployment_2_java_configuration.yml
    deployment_2_java_eureka.yml
    deployment_2_java_other.yml
    deployment_2_nginx_erp.yml
    deployment_3_volumes_search_p1.yml
    deployment_3_volumes_search_p2.yml
    service.yml
)
function download_ci_file_kubernetes (){
    # 原始gitlab上的目录和下载到的jenkins的工作空间的目录
    source_dir="./jenkins_build/kubernetes"
    target_dir="$url_jenkins_scripts/devb/kubernetes"
    # 逐个下载文件   
    # for file in $(echo $kubernetes_list)  # 这个是kubernetes_list="" 这种方式的列表遍历读取
    for file in ${kubernetes_list[@]}
    do
        # echo $file
        curl -s -o $source_dir/$file $target_dir/$file
    done
}
# 调用函数，下载文件
download_ci_file_kubernetes
# 命名构建三剑客文件
path_dockerfile="$WORKSPACE/jenkins_build/docker/Dockerfile"
path_k8s_deployment="$WORKSPACE/jenkins_build/kubernetes/deployment.yml"
path_k8s_service="$WORKSPACE/jenkins_build/kubernetes/service.yml"



# =============================== <打包成docker镜像并推送到harbor仓库> ===========================
# ------------------------------------变量定义---------------------------------------

# 手动引入IP变量
source /etc/profile.d/ip_lan1.sh
echo "本机IP为: $IP_LAN1"

# env_docker_image: 镜像环境，在harbor里作为表示为项目
# env_k8s_args: 发布环境，微服务启动时的参数中的变量

# 默认的docker镜像仓库url，生产环境可能会是个新的，需要在if里面再定义
# 注：harbor的url不需要写http和端口，只写域名或者IP即可
registry_url_default="okms-harbor.xbazhen.com"
registry_url=$registry_url_default

if [ "$IP_LAN1" = "172.16.10.40" ];
then
    env_docker_image="okms-test"
	env_k8s_args="test"

elif [ "$IP_LAN1" = "172.16.10.50" ];
then
    env_docker_image="okms-prod"
    env_k8s_args="prod"
fi
echo "harbor项目为: $env_docker_image"

# 镜像名定义
find_jar=$(find $WORKSPACE -name "target" -type d)
if [ ! -z "$find_jar" ]
then
    # echo "java"
    # 服务类型为java应用
    # 排除xxx-xxx-sources.jar的这种jar包
    image_name="$(ls $WORKSPACE/target | egrep *.jar$ | awk -F'.' '{print $1}' | grep -v "\-sources$")"
elif [ -f "$WORKSPACE/src/main/image_info.sh" ]
then
    # echo "html"
    # 服务类型为其他，例如html应用
    source $WORKSPACE/src/main/image_info.sh
else
    # 如果上述两种均未获取到
    # 这个暂时只适用于git项目，svn项目后续再做兼容
    # 也不能选取jenkins的项目名，因为那个名字可能会起的很奇怪
    image_name="$(cd $WORKSPACE; git config -l | grep 'remote.origin.url' | tr '/' '\n' | grep '.git$' | awk -F'.' '{print $1}')"   
fi
echo "镜像名为: $image_name"


# 端口名定义，按照应该部署的顺序排序
if [ "$image_name" == "okms-ui" ]
then
    container_port1="80";   svc_node_port1="30101"

# elif [ "$image_name" == "eureka-service" ]
# then
#     container_port1="8761"; svc_node_port1="30000"

# elif [ "$image_name" == "configuration-service" ]
# then
#     container_port1="8888"; svc_node_port1="30002"

# elif [ "$image_name" == "zipkin-service" ]
# then
#     container_port1="9888"; svc_node_port1="30005"

# elif [ "$image_name" == "redis-service" ]
# then
#     container_port1="9018"; svc_node_port1="30004"

# elif [ "$image_name" == "common-service" ]
# then
#     container_port1="9008"; svc_node_port1="30006"

# elif [ "$image_name" == "user-service" ]
# then
#     container_port1="9012"; svc_node_port1="30007"

# elif [ "$image_name" == "erp" ]
# then
#     container_port1="9033"; svc_node_port1="30010"

# elif [ "$image_name" == "front" ]
# then
#     container_port1="9022"; svc_node_port1="30008"

# elif [ "$image_name" == "gateway-back-end" ]
# then
#     container_port1="9090"; svc_node_port1="30009"

# elif [ "$image_name" == "product-service" ]
# then
#     container_port1="9017"; svc_node_port1="30011"

# elif [ "$image_name" == "stock-service" ]
# then
#     container_port1="9013"; svc_node_port1="30012"

# elif [ "$image_name" == "supplier-service" ]
# then
#     container_port1="9025"; svc_node_port1="30013"        

# elif [ "$image_name" == "activiti-service" ]
# then
#     container_port1="9002"; svc_node_port1="30014"

# elif [ "$image_name" == "hystrix-service" ]
# then
#     container_port1="8989"; svc_node_port1="30015"

# elif [ "$image_name" == "search-service" ]
# then
#     container_port1="9034"; svc_node_port1="30016"

# elif [ "$image_name" == "order-service" ]
# then
#     container_port1="9088"; svc_node_port1="30017"

# elif [ "$image_name" == "mq-service" ]
# then
#     container_port1="9055"; svc_node_port1="30018"

fi
# k8s 的 service的cluster ip的 port一般和 容器端口一致
svc_cluster_port1="$container_port1"
# image_name="common-service"
# echo $container_port1


# git版本号，和下面一起用作镜像的tag名
git_revision=$(git show --oneline | head -n 1 | awk '{print $1}')
image_version_1="v$(date +%Y%m%d_%H%M%S)_${git_revision}"
image_version_2="latest"
# 镜像完整名（加上仓库和在仓库的项目）
image_url="$registry_url/$env_docker_image/$image_name"
image_url_v1="$image_url:$image_version_1"
image_url_v2="$image_url:$image_version_2"



# ----------------------------------构建docker镜像-------------------------------------
# 进入工作目录
cd $WORKSPACE

# 合并文件: 先合并,再替换变量
# 第一个文件是直接覆盖到 deployment.yml
if [ "$image_name" == "okms-ui" ]
then
    cat ./jenkins_build/docker/Dockerfile_nginx > ./jenkins_build/docker/Dockerfile

else
    cat ./jenkins_build/docker/Dockerfile_java > ./jenkins_build/docker/Dockerfile
fi
# 替换文件内的变量
sed -i "s/VAR_IMAGE_NAME/$image_name/g" $path_dockerfile
sed -i "s/VAR_CONTAINER_PORT1/$container_port1/g" $path_dockerfile
# 更新 FROM 字段后面的镜像，如果不更新的话，由于tag一样，会取本地缓存
from_image_url=$(cat $path_dockerfile | egrep -v ^# | grep 'FROM' | awk '{print $2}')
docker pull $from_image_url
# docker pull harbor.lovego2016.com/base/centos7-nginx1-12:latest
# docker pull harbor.lovego2016.com/base/centos7-jdk8:latest
# 构建镜像并打tag
docker build -t $image_url_v1 -f $path_dockerfile .
# 打最新的tag
docker tag $image_url_v1 $image_url_v2
# 推送镜像到仓库
docker push $image_url_v1
docker push $image_url_v2


# 如果出现登陆异常,请手动执行登陆
# docker login -u admin -p Harbor12345 harbor.test.com


# --------------------------------清理本地jenkins历史tag----------------------------------
# 只保留latest及v开头最新的5个，一共6个
# 如果不足6个的话，会失败，所以仅在大于6个的时候才删除
image_tag_num=$(docker images | grep $image_url | wc -l)
if [ $image_tag_num -gt 6 ];
then
	docker rmi $(docker images | grep $image_url | grep -v latest | sort -k2 -rn | sed '1,5 d' | awk '{print $3}') --force
fi
# 注：对于一个服务，即使一模一样的git版本，所生成的镜像的id也不一样






# ======================== <发布到Kubernetes集群内部，若已发布，则更新版本> =========================
# --------------------------------发布到Kubernetes----------------------------------
# 前置条件1
# 需要自动为jenkins配置Kubernetes的kubectl管理
# kubectl config view
# kubectl get nodes
# 前置条件2
# 需要在rancher上面，保存一个具有harbor管理员权限的账户，不然kubernetes在创建deployment拉取不下来镜像
# 

# 镜像名
# image_name="$(ls $WORKSPACE/target | egrep *.jar$ | awk -F'.' '{print $1}')"
deployment_name="deploy-$image_name"
service_name="svc-$image_name"
#container_name="container-$image_name"

# 合并文件: 先合并,再替换变量
# 第一个文件是直接覆盖到 deployment.yml
cat ./jenkins_build/kubernetes/deployment_1.yml > ./jenkins_build/kubernetes/deployment.yml
# 第二个文件时向 deployment.yml 进行追加
if [ "$image_name" == "okms-ui" ]
then
    cat ./jenkins_build/kubernetes/deployment_2_nginx_erp.yml >> ./jenkins_build/kubernetes/deployment.yml

elif [ "$image_name" == "eureka-service" ]
then
    cat ./jenkins_build/kubernetes/deployment_2_java_eureka.yml >> ./jenkins_build/kubernetes/deployment.yml

elif [ "$image_name" == "configuration-service" ]
then
    cat ./jenkins_build/kubernetes/deployment_2_java_configuration.yml >> ./jenkins_build/kubernetes/deployment.yml

else
    cat ./jenkins_build/kubernetes/deployment_2_java_other.yml >> ./jenkins_build/kubernetes/deployment.yml
fi
# 第三个文件，添加挂载卷的配置，以后会对这种更新配置文件的方式进行重构
if [ "$image_name" == "search-service" ]
then
    # 这个追加文件的顺序要保证是对的
    cat ./jenkins_build/kubernetes/deployment_3_volumes_search_p2.yml >> ./jenkins_build/kubernetes/deployment.yml
    cat ./jenkins_build/kubernetes/deployment_3_volumes_search_p1.yml >> ./jenkins_build/kubernetes/deployment.yml
fi

# 替换文件内的变量
# 变量image_url_v1的值有 / ，需要把sed s的符号改成 #
# deployment.yml
sed -i "s#VAR_IMAGE_URL#$image_url_v1#g"              $path_k8s_deployment
sed -i "s/VAR_IMAGE_NAME/$image_name/g"               $path_k8s_deployment
sed -i "s/VAR_CONTAINER_PORT1/$container_port1/g"     $path_k8s_deployment
sed -i "s/VAR_K8S_ENV/$env_k8s_args/g"                     $path_k8s_deployment
# service.yml
sed -i "s/VAR_IMAGE_NAME/$image_name/g"               $path_k8s_service
sed -i "s/VAR_CONTAINER_PORT1/$container_port1/g"     $path_k8s_service
sed -i "s/VAR_SVC_CLUSTER_PORT1/$svc_cluster_port1/g" $path_k8s_service
sed -i "s/VAR_SVC_NODE_PORT1/$svc_node_port1/g"       $path_k8s_service


if [ "$(kubectl get deployments $deployment_name)" ]
then
	deployment_exist=1
    # kubectl set image deployment/$deployment_name $container_name=$image_url_v1
    # apply更新的方式更为完善
    echo "本Deployment已存在，自动从部署文件更新配置(包括应用最新版本的镜像)..."
    kubectl apply -f $path_k8s_deployment --record
else
	deployment_exist=0
    echo "本Deployment不存在，开始创建..."
	kubectl create -f $path_k8s_deployment --record
fi
# echo $deployment_exist

if [ "$(kubectl get services $service_name)" ]
then
	service_exist=1
    echo "本Service已存在，自动从部署文件更新配置..."
    kubectl apply -f $path_k8s_service --record
else
	service_exist=0
    echo "本Service不存在，开始创建..."
    kubectl create -f $path_k8s_service --record
fi
# echo $service_exist
